package com.edee.bigday.commodity;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * 1、整合MyBatis-plus：
 *   1）导入依赖：
 *      <dependency>
 *             <groupId>com.baomidou</groupId>
 *             <artifactId>mybatis-plus-boot-starter</artifactId>
 *             <version>3.4.1</version>
*       </dependency>
 *   2）配置
 *      A、配置数据源；
 *          a、导入数据库驱动：
 *          <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
 *          <dependency>
 *              <groupId>mysql</groupId>
 *              <artifactId>mysql-connector-java</artifactId>
 *              <version>8.0.22</version>
 *          </dependency>
 *          b、在application.yml中配置数据源相关信息。
 *
 *      B、配置MyBatis-plus相关信息。
 *      https://baomidou.com/guide/install.html#release
 *          a、使用@MapperScan扫描mapper接口
 *          b、告诉MyBatis-plus，sql的.xml映射文件位置。
 * 2、逻辑删除：
 *      1）配置全局的逻辑删除；（高于3.3.0的版本可省略）
 *          mybatis-plus:
         *   global-config:
         *     db-config:
         *       logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
         *       logic-delete-value: 1 # 逻辑已删除值(默认为 1)
         *       logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
 *      2）配置逻辑删除的组件，注册Bean（3.1.1开始不再需要这一步）；
 *          @Bean
 *          public ISqInjector sqlInjector(){
 *              return new LogicSqlInjector();
 *          }
 *      3）实体类字段上加上@TableLogic注解，如：
 *          @TableLogic
 *          private Integer deleted;
 *       本例：
 *          @TableLogic(value = "1", delval = "0")
 *          private Integer showStatus;
 *
 *  3、JSR303:
 *      1）给Bean添加校验注解:import javax.validation.constraints.NotBlank，并自定义message提示;
 *      2）在需要校验的字段前添加注解：@Valid。效果：校验失败，即给出默认响应。
 *      3）在需要校验的Bean后紧跟一个BindingResult，即可获取到校验结果；
 *      4）分组校验(可以完成多场景的复杂校验)：
 *          a、在注解上标注需要校验的操作，如，@NotBlank(message = "品牌名必须非空！", groups = {AddGroup.class, UpdateGroup.class})
 *          b、在Controller里标注需要校验的操作，如，@Validated({AddGroup.class})
 *          c、在Controller中使用诸如@Validated({AddGroup.class})指明分组校验时，需要在Entity中为待校验的字段指定分组，
 *          否则将不予校验。在Entity中不指定校验分组，只有在使用@Validated(无校验分组)时才生效。
 *      5）自定义校验：
 *          a、编写一个自定义的校验注解；
 *          b、编写一个自定义的校验器，如：ConstraintValidator；
 *          c、关联自定义的校验注解和校验器，在自定义校验注解上添加如下注解：
 *              @Documented
 *              @Constraint(validatedBy = { ListValueConstraintValidator.class }) //可以指定多个校验器
 *              @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
 *              @Retention(RUNTIME)
 *
 *  4、统一的异常处理：
 *      使用SpringMVC的@ControllerAdvice
 *      1）编写异常处理类，使用@ControllerAdvice（最终使用RestControllerAdvice代替@ControllerAdvice和@ResponseBody）；
 *      2）使用ExceptionHandler标注方法可以处理的异常。
 *  5、模板引擎thymeleaf：
 *      1）引入thymeleaf-starter，关闭缓存；
 *      2）静态资源放在static文件夹中，就可以直接按照路径访问，如：
 *          http://localhost:7000/index/css/GL.css
 *          http://localhost:7000/index/img/1.png
 *      3）页面(如index.html)放在template文件夹中，也可以直接访问。
 *          另外，在SpringBoot中访问项目(如http://localhost:7000/)时，默认访问index.html。
 *          这些默认配置放在D:/Soft-Dellvostro/Soft/Java/apache-maven-3.6.3/repository/org/springframework/boot/spring-boot-autoconfigure/2.3.2.RELEASE/spring-boot-autoconfigure-2.3.2.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java
 *          默认规则包含：
 *          hasMappingForPattern("/webjars/**")：默认访问的资源；
 *          addResourceLocations("classpath:/META-INF/resources/webjars/")：默认查找类路径下的resources/webjars
 *          WelcomePageHandlerMapping：欢迎页映射规则，在this.mvcProperties.getStaticPathPattern()的
 *          getStaticPathPattern()，由此进入D:/Soft-Dellvostro/Soft/Java/apache-maven-3.6.3/repository/org/springframework/boot/spring-boot-autoconfigure/2.3.2.RELEASE/spring-boot-autoconfigure-2.3.2.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/web/servlet/WebMvcProperties.java，
 *          private Resource getIndexHtml(String location) {
 * 			return this.resourceLoader.getResource(location + "index.html");
 *                }
 *          其中，src/main/resources是类路径，也可以改成其它任意名称。如：
 *          D:/Soft-Dellvostro/Soft/Java/apache-maven-3.6.3/repository/org/springframework/boot/spring-boot-autoconfigure/2.3.2.RELEASE/spring-boot-autoconfigure-2.3.2.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/web/ResourceProperties.java
 *          中的：
 *          private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
 * 			"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
 * 		    classpath即为src/main/resources。
 * 		4）在不重启服务器的情况下，修改页面实时更新：
 * 	        4.1）引入SpringBoot提供的dev-tools依赖；
 * 	            <dependency>
     *             <groupId>org.springframework.boot</groupId>
 *      *             <artifactId>spring-boot-devtools</artifactId>
 *      *             <optional>true</optional>
 *      *         </dependency>
 *          4.2）Ctrl+Shift+F9（或Ctrl+F9）自动编译页面（实测此步骤不需要，直接保存即可实时更新）；
 *              如果涉及代码配置改动，最好重启服务。
 *          4.3）关闭缓存：在application.yml中：
 *              thymeleaf:
 *                  cache: false
 *  6、整合Redis：
 *      6.1）引入spring-boot-starter-data-redis依赖；
 *      6.2）简单配置redis的host信息；
 *      6.3）使用SpringBoot自动配置好的StringRedisTemplate来操作Redis；
 *          Redis类似于Map，存放Key,Value对。
 *  7、整合Redisson作为分布式锁等功能的框架：
 *      7.1）引入依赖；
 *      7.2）配置与使用Redisson（参考官方文档）
 *  8、整合SpringCache，简化开发：
 *      8.1）引入依赖：spring-boot-starter-cache和spring-boot-starter-data-redis(之前已经引入)
 *      8.2）编写配置-自动配置：
 *          a、自动配置，在CacheAutoConfiguration中：@EnableConfigurationProperties(CacheProperties.class)
 *              CacheProperties.java中封装的是xml文件中需要配置的内容。
 *          b、自动配置，在CacheAutoConfiguration中：static class CacheConfigurationImportSelector implements ImportSelector中d
 *              imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
 *              Ctrl+单击getConfigurationClass()方法名，进入D:/Soft-Dellvostro/Soft/Java/apache-maven-3.6.3/repository/org/springframework/boot/spring-boot-autoconfigure/2.2.12.RELEASE/spring-boot-autoconfigure-2.2.12.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/cache/CacheProperties.java，
 *              可以看到：Class<?> configurationClass = MAPPINGS.get(cacheType);，查看MAPPINGS：
 *              mappings.put(CacheType.REDIS, RedisCacheConfiguration.class);
 *          c、综上，自动配置时，CacheAutoConfiguration会导入RedisCacheConfiguration。
 *          d、再Ctrl+单击RedisCacheConfiguration，可以看到：
 *              @Bean
 *              RedisCacheManager cacheManager
 *              说明已经已经自动配置了缓存过滤器RedisCacheManager。
 *      8.3）编写自定义配置：使用Redis作为缓存，在application.properties配置：spring.cache.type=redis
 *      8.4）测试使用缓存：
 *          @Cacheable: Triggers cache population. 触发将数据保存到缓存的操作；
 *          @CacheEvict: Triggers cache eviction. 触发将数据从缓存删除的操作；
 *          @CachePut: Updates the cache without interfering with the method execution.不影响方法执行更新缓存；
 *          @Caching: Regroups multiple cache operations to be applied on a method. 组合以上多个缓存；
 *          @CacheConfig: Shares some common cache-related settings at class-level. 在类级别共享缓存的相同配置；
 *          8.4.1）开启缓存功能：@EnableCaching；
 *          8.4.2）只要使用注解就能完成缓存操作。
 *      8.5）SpringCache原理：
 *             org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration-->org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration-->自动配置了RedisCacheManager-->初始化所有的缓存-->每个缓存决定使用什么配置
 *             -->如果org.springframework.data.redis.cache.RedisCacheConfiguration中有，就用已有的。如果没有，就用默认配置。-->想要修改缓存的配置，只需要在容器Bean中放一个org.springframework.data.redis.cache.RedisCacheConfiguration配置类即可
 *             -->该RedisCacheConfiguration就会应用到当前RedisCacheManager管理的所有缓存分区中。
 */
//@EnableCaching  //移至自定义配置com.edee.bigday.commodity.config.MyCacheConfig中。
@EnableFeignClients(basePackages = "com.edee.bigday.commodity.feign")
@MapperScan("com.edee.bigday.commodity.dao")
@SpringBootApplication
@EnableDiscoveryClient
//开启session的Redis存储功能：
@EnableRedisHttpSession
public class BigdayCommodityApplication {

    public static void main(String[] args) {
        SpringApplication.run(BigdayCommodityApplication.class, args);
    }

}
